"""
用户模型
支持工单系统的用户认证和权限管理
"""

from datetime import datetime
from typing import Optional, List, Dict, Any, Set
import uuid
from enum import Enum
from pydantic import BaseModel, Field
from sqlalchemy import Column, String, DateTime, Boolean, Enum as SQLEnum, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from src.config.database import Base


class UserRole(str, Enum):
    """用户角色枚举"""
    ADMIN = "admin"        # 管理员：完全系统访问权限
    AGENT = "agent"        # 客服：处理工单权限
    USER = "user"          # 普通用户：创建和查看自己的工单


class UserStatus(str, Enum):
    """用户状态枚举"""
    ACTIVE = "active"      # 活跃用户
    INACTIVE = "inactive"  # 非活跃用户
    SUSPENDED = "suspended" # 已暂停用户


class User(Base):
    """用户数据模型"""
    __tablename__ = "users"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    username = Column(String(50), unique=True, nullable=False, index=True)
    email = Column(String(100), unique=True, nullable=False, index=True)
    password_hash = Column(String(255), nullable=False)
    password_history = Column(Text, nullable=True)  # JSON格式的密码历史记录
    display_name = Column(String(100), nullable=True)
    role = Column(SQLEnum(UserRole), default=UserRole.USER, nullable=False)
    status = Column(SQLEnum(UserStatus), default=UserStatus.ACTIVE, nullable=False)
    phone_number = Column(String(255), nullable=True)  # 加密存储，增加长度
    avatar_url = Column(String(255), nullable=True)
    department = Column(String(255), nullable=True)  # 加密存储，增加长度
    last_login_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    user_metadata = Column(Text, nullable=True)  # JSON格式的额外元数据

    # 关系
    group_associations = relationship("UserGroup", back_populates="user", cascade="all, delete-orphan")


class UserCreate(BaseModel):
    """创建用户的请求模型"""
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: str = Field(..., description="邮箱地址")
    password: str = Field(..., min_length=6, description="密码")
    display_name: Optional[str] = Field(None, max_length=100, description="显示名称")
    phone_number: Optional[str] = Field(None, max_length=20, description="手机号码")
    department: Optional[str] = Field(None, max_length=100, description="部门")
    role: UserRole = Field(default=UserRole.USER, description="用户角色")


class UserUpdate(BaseModel):
    """更新用户的请求模型"""
    display_name: Optional[str] = Field(None, max_length=100, description="显示名称")
    email: Optional[str] = Field(None, description="邮箱地址")
    phone_number: Optional[str] = Field(None, max_length=20, description="手机号码")
    department: Optional[str] = Field(None, max_length=100, description="部门")
    role: Optional[UserRole] = Field(None, description="用户角色")
    status: Optional[UserStatus] = Field(None, description="用户状态")


class UserResponse(BaseModel):
    """用户响应模型"""
    id: uuid.UUID
    username: str
    email: str
    display_name: Optional[str]
    role: UserRole
    status: UserStatus
    phone_number: Optional[str]
    avatar_url: Optional[str]
    department: Optional[str]
    last_login_at: Optional[datetime]
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True
        arbitrary_types_allowed = True


class UserLogin(BaseModel):
    """用户登录请求模型"""
    username: str = Field(..., description="用户名或邮箱")
    password: str = Field(..., description="密码")


class Token(BaseModel):
    """认证令牌响应模型"""
    access_token: str
    refresh_token: Optional[str] = None
    token_type: str = "bearer"
    expires_in: int


class TokenData(BaseModel):
    """令牌数据模型"""
    user_id: Optional[uuid.UUID] = None
    username: Optional[str] = None
    role: Optional[UserRole] = None
    exp: Optional[datetime] = None


class Permission:
    """权限控制类"""
    
    # 定义权限常量
    CREATE_TICKET = "create_ticket"
    VIEW_ALL_TICKETS = "view_all_tickets"
    ASSIGN_TICKETS = "assign_tickets"
    CLOSE_TICKETS = "close_tickets"
    MANAGE_USERS = "manage_users"
    VIEW_STATS = "view_stats"
    MANAGE_GROUPS = "manage_groups"
    VIEW_KNOWLEDGE_BASE = "view_knowledge_base"
    EDIT_KNOWLEDGE_BASE = "edit_knowledge_base"
    
    @staticmethod
    def get_role_permissions(role: UserRole) -> Set[str]:
        """获取角色对应的权限集合"""
        permissions = set()
        
        if role == UserRole.ADMIN:
            # 管理员拥有所有权限
            permissions = {
                Permission.CREATE_TICKET,
                Permission.VIEW_ALL_TICKETS,
                Permission.ASSIGN_TICKETS,
                Permission.CLOSE_TICKETS,
                Permission.MANAGE_USERS,
                Permission.VIEW_STATS,
                Permission.MANAGE_GROUPS,
                Permission.VIEW_KNOWLEDGE_BASE,
                Permission.EDIT_KNOWLEDGE_BASE
            }
        elif role == UserRole.AGENT:
            # 客服权限
            permissions = {
                Permission.CREATE_TICKET,
                Permission.VIEW_ALL_TICKETS,
                Permission.ASSIGN_TICKETS,
                Permission.CLOSE_TICKETS,
                Permission.VIEW_STATS,
                Permission.VIEW_KNOWLEDGE_BASE
            }
        elif role == UserRole.USER:
            # 普通用户权限
            permissions = {
                Permission.CREATE_TICKET,
                Permission.VIEW_KNOWLEDGE_BASE
            }
            
        return permissions
    
    @staticmethod
    def has_permission(user_role: UserRole, permission: str) -> bool:
        """检查用户角色是否具有特定权限"""
        role_permissions = Permission.get_role_permissions(user_role)
        return permission in role_permissions
    
    @staticmethod
    def can_create_ticket(user_role: UserRole) -> bool:
        """检查用户是否有权限创建工单"""
        return Permission.has_permission(user_role, Permission.CREATE_TICKET)
    
    @staticmethod
    def can_view_all_tickets(user_role: UserRole) -> bool:
        """检查用户是否有权限查看所有工单"""
        return Permission.has_permission(user_role, Permission.VIEW_ALL_TICKETS)
    
    @staticmethod
    def can_assign_tickets(user_role: UserRole) -> bool:
        """检查用户是否有权限分配工单"""
        return Permission.has_permission(user_role, Permission.ASSIGN_TICKETS)
    
    @staticmethod
    def can_close_tickets(user_role: UserRole) -> bool:
        """检查用户是否有权限关闭工单"""
        return Permission.has_permission(user_role, Permission.CLOSE_TICKETS)
    
    @staticmethod
    def can_manage_users(user_role: UserRole) -> bool:
        """检查用户是否有权限管理用户"""
        return Permission.has_permission(user_role, Permission.MANAGE_USERS)
    
    @staticmethod
    def can_view_stats(user_role: UserRole) -> bool:
        """检查用户是否有权限查看统计信息"""
        return Permission.has_permission(user_role, Permission.VIEW_STATS)
